package com.test.mylotterysystem.service.Impl;

import com.test.mylotterysystem.comment.errorCode.ServiceErrorCode;
import com.test.mylotterysystem.comment.exception.ServiceException;
import com.test.mylotterysystem.comment.utils.*;
import com.test.mylotterysystem.controller.Param.LoginParam;
import com.test.mylotterysystem.controller.Param.PasswordLoginParam;
import com.test.mylotterysystem.controller.Param.UserRegisterParam;
import com.test.mylotterysystem.controller.Param.VerificationCodeLoginParam;
import com.test.mylotterysystem.dao.DO.Encrypt;
import com.test.mylotterysystem.dao.DO.UserDO;
import com.test.mylotterysystem.dao.Mapper.UserMapper;
import com.test.mylotterysystem.service.DTO.UserInfoDTO;
import com.test.mylotterysystem.service.DTO.UserLoginDTO;
import com.test.mylotterysystem.service.DTO.UserRegisterDTO;
import com.test.mylotterysystem.service.UserService;
import com.test.mylotterysystem.service.serviceEnum.UserAdmin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private SMSUtil smsUtil;

    @Autowired
    private RedisUtil redisUtil;

    private static final String VERIFICATION_CODE_PREFIX = "VERIFICATION_CODE_";

    private static final long VERIFICATION_CODE_TIMEOUT = 5 * 60L;

    /**
     * 用户注册
     *
     * @param userRegisterParam
     * @return
     */
    @Override
    public UserRegisterDTO register(UserRegisterParam userRegisterParam) {
        // 对用户数据进行校验
        checkUserInfo(userRegisterParam);

        // 封装对象并存储到数据库中
        UserDO userDO = new UserDO();
        userDO.setUserName(userRegisterParam.getName());
        userDO.setEmail(userRegisterParam.getMail());
        userDO.setPhoneNumber(new Encrypt(userRegisterParam.getPhoneNumber()));
        userDO.setPassword(userRegisterParam.getPassword() == null ? null : SecurityUtil.encrypt(userRegisterParam.getPassword()));
        userDO.setIdentity(userRegisterParam.getIdentity());
        userMapper.insertUserInfo(userDO);

        // 返回结果
        return new UserRegisterDTO(userDO.getId());
    }

    /**
     * 校验用户数据
     *
     * @param userRegisterParam
     */
    private void checkUserInfo(UserRegisterParam userRegisterParam) {
        // 校验用户信息不为空
        if (userRegisterParam == null) {
            throw new ServiceException(ServiceErrorCode.USER_INFO_IS_EMPTY);
        }

        // 校验用户名是否重复
        int nameCount = userMapper.checkUserName(userRegisterParam.getName());
        if (nameCount > 0) {
            throw new ServiceException(ServiceErrorCode.USER_NAME_HAS_EXIST);
        }

        // 校验邮箱
        if (!RegexUtil.checkMailFormat(userRegisterParam.getMail())) {
            throw new ServiceException(ServiceErrorCode.MAIL_FORMAT_IS_ERROR);
        }

        int mailCount = userMapper.checkUserMail(userRegisterParam.getMail());
        if (mailCount > 0) {
            throw new ServiceException(ServiceErrorCode.MAIL_HAS_EXIST);
        }

        // 校验手机号
        if (!RegexUtil.checkPhoneFormat(userRegisterParam.getPhoneNumber())) {
            throw new ServiceException(ServiceErrorCode.PHONE_FORMAT_IS_ERROR);
        }

        int phoneCount = userMapper.checkPhone(userRegisterParam.getPhoneNumber());
        if (phoneCount > 0) {
            throw new ServiceException(ServiceErrorCode.PHONE_HAS_EXIST);
        }

        // 校验密码
        if (userRegisterParam.getPassword() != null && StringUtils.hasText(userRegisterParam.getPassword()) &&
                !RegexUtil.checkPasswordFormat(userRegisterParam.getPassword())) {
            throw new ServiceException(ServiceErrorCode.PASSWORD_FORMAT_IS_ERROR);
        }

        // 校验身份
        if (!userRegisterParam.getIdentity().equalsIgnoreCase(UserAdmin.ADMIN.name()) &&
                !userRegisterParam.getIdentity().equalsIgnoreCase(UserAdmin.NORMAL.name())) {
            throw new ServiceException(ServiceErrorCode.USER_IDENTITY_IS_ERROR);
        }
    }

    /**
     * 发送短信
     *
     * @param phoneNumber
     * @return
     */
    @Override
    public boolean verificationCode(String phoneNumber) {
        // 校验手机号是否正确
        if (!RegexUtil.checkPhoneFormat(phoneNumber)) {
            throw new ServiceException(ServiceErrorCode.PHONE_FORMAT_IS_ERROR);
        }

        // 获取短信验证码
        String captcha = MyCaptchaUtil.getCaptcha(4);

        // 发送短信验证码
        Map<String, String> map = new HashMap<>();
        map.put("code", captcha);
        smsUtil.sendMessage("SMS_154950909",
                phoneNumber,
                JacksonUtil.writeValueAsString(map));

        // 将短信验证码存储在redis中
        return redisUtil.set(VERIFICATION_CODE_PREFIX + phoneNumber, captcha, VERIFICATION_CODE_TIMEOUT);
    }

    /**
     * 用户登录
     *
     * @param loginParam
     * @return
     */
    @Override
    public UserLoginDTO login(LoginParam loginParam) {
        // 校验数据
        checkLoginInfo(loginParam);

        // 验证是否可以登录
        UserLoginDTO userLoginDTO = null;
        if (loginParam instanceof PasswordLoginParam passwordParam) {
            userLoginDTO = checkPasswordLogin(passwordParam);
        } else if (loginParam instanceof VerificationCodeLoginParam verificationCodeParam) {
            userLoginDTO = checkVerificationCodeLogin(verificationCodeParam);
        } else {
            throw new ServiceException(ServiceErrorCode.USER_LOGIN_PARAM_TYPE_IS_ERROR);
        }

        // 返回结果
        return userLoginDTO;
    }


    /**
     * 判断使用验证码是否可以登录
     *
     * @param verificationCodeParam
     * @return
     */
    private UserLoginDTO checkVerificationCodeLogin(VerificationCodeLoginParam verificationCodeParam) {
        // 判断是否存在用户
        UserDO userDO = userMapper.selectByPhoneNumber(new Encrypt(verificationCodeParam.getPhoneNumber()));
        if (userDO == null) {
            throw new ServiceException(ServiceErrorCode.USER_NOT_EXIST);
        }

        // 判断验证码是否正确
        if (!redisUtil.get(VERIFICATION_CODE_PREFIX + verificationCodeParam.getPhoneNumber())
                .equals(verificationCodeParam.getVerificationCode())) {
            throw new ServiceException(ServiceErrorCode.USER_VERIFICATION_CODE_IS_ERROR);
        }

        // 返回值
        Map<String, Object> map = new HashMap<>();
        map.put("userId", userDO.getId());
        map.put("identity", userDO.getIdentity());
        String token = JWTUtil.genJwt(map);

        UserLoginDTO userLoginDTO = new UserLoginDTO();
        userLoginDTO.setToken(token);
        userLoginDTO.setIdentity("ADMIN");

        return userLoginDTO;
    }

    /**
     * 判断使用密码是否可以登录
     *
     * @param passwordParam
     * @return
     */
    private UserLoginDTO checkPasswordLogin(PasswordLoginParam passwordParam) {
        // 判断是否存在用户
        UserDO userDO = userMapper.selectByPhoneNumber(new Encrypt(passwordParam.getPhoneNumber()));
        if (userDO == null) {
            throw new ServiceException(ServiceErrorCode.USER_NOT_EXIST);
        }

        // 判断密码是否正确
        if (!SecurityUtil.verify(passwordParam.getPassword(), userDO.getPassword())) {
            throw new ServiceException(ServiceErrorCode.USER_PASSWORD_IS_ERROR);
        }

        // 返回值
        Map<String, Object> map = new HashMap<>();
        map.put("userId", userDO.getId());
        map.put("identity", userDO.getIdentity());
        String token = JWTUtil.genJwt(map);

        UserLoginDTO userLoginDTO = new UserLoginDTO();
        userLoginDTO.setToken(token);
        userLoginDTO.setIdentity("ADMIN");

        return userLoginDTO;
    }

    /**
     * 校验登录数据是否合法
     *
     * @param loginParam
     */
    private void checkLoginInfo(LoginParam loginParam) {
        if (loginParam == null) {
            throw new ServiceException(ServiceErrorCode.USER_LOGIN_INFO_IS_EMPTY);
        }
        if (!RegexUtil.checkPhoneFormat(loginParam.getPhoneNumber())) {
            throw new ServiceException(ServiceErrorCode.PHONE_FORMAT_IS_ERROR);
        }
        if (!loginParam.getMandatoryIdentity().equalsIgnoreCase(UserAdmin.ADMIN.name())) {
            throw new ServiceException(ServiceErrorCode.USER_IDENTITY_IS_NOT_ADMIN);
        }
    }

    /**
     * 获取用户列表
     *
     * @param identity
     * @return
     */
    @Override
    public List<UserInfoDTO> getUserInfoList(String identity) {
        if (identity != null &&
                !identity.equalsIgnoreCase(UserAdmin.ADMIN.name()) &&
                        !identity.equalsIgnoreCase(UserAdmin.NORMAL.name())) {
            throw new ServiceException(ServiceErrorCode.USER_FIND_IDENTITY_IS_ERROR);
        }

        List<UserDO> userDOS = userMapper.getUserInfoList(identity);
        return userDOS == null ? null : MyBeanUtil.transOfListUserInfoDTO(userDOS);
    }
}
